package com.zxy.ziems.server.statistics.service.impl;

import cn.hutool.core.lang.tree.Tree;
import com.zxy.ziems.server.constant.DateType;
import com.zxy.ziems.server.domain.DictItem;
import com.zxy.ziems.server.dto.DataQueryDto;
import com.zxy.ziems.server.dto.DateDto;
import com.zxy.ziems.server.energy.service.DataChartService;
import com.zxy.ziems.server.service.DictItemService;
import com.zxy.ziems.server.statistics.constants.Constants;
import com.zxy.ziems.server.statistics.pojo.vo.HomologyChainBodyVO;
import com.zxy.ziems.server.statistics.pojo.vo.HomologyChainVO;
import com.zxy.ziems.server.statistics.service.HomologyChainService;
import com.zxy.ziems.server.statistics.util.HomologyChainExportUtil;
import com.zxy.ziems.server.utils.AssertUtil;
import com.zxy.ziems.server.utils.DateUtils;
import com.zxy.ziems.server.vo.ChartVo;
import com.zxy.ziems.server.vo.ReportDataVo;
import com.zxy.ziems.server.vo.ReportVo;
import jakarta.servlet.http.HttpServletResponse;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class HomologyChainServiceImpl implements HomologyChainService {

    @Autowired
    private DataChartService dataChartService;
    @Autowired
    private DictItemService dictItemService;

    @Override
    public HomologyChainVO list(DataQueryDto dataQueryDto, Integer homologyType) {

        HomologyChainVO result = new HomologyChainVO();

        Constants.HomologyTypeEnum homologyTypeEnum = Constants.HomologyTypeEnum.getByCode(homologyType);

        AssertUtil.nonNull(homologyTypeEnum, "同环比类型不可为空");

        //根据查询条件计算起止时间
        String queryType = dataQueryDto.getQueryType();
        String startDay = dataQueryDto.getStartDay();
        DateDto dateDto = DateUtils.dateQueryConvert(queryType, dataQueryDto.getStartDay(), dataQueryDto.getEndDay(), false);
        //构建x轴
        List<LocalDateTime> list = DateUtils.dateToList(queryType, dateDto.getStartDay(), dateDto.getEndDay());
        List<String> headers = new ArrayList<>();
        result.setHeaders(headers);
        for (LocalDateTime localDateTime : list) {
            headers.add(localDateTime.toLocalDate().toString());
        }
        List<String> queryIdList = dataQueryDto.getClassifyIdList();
        AssertUtil.nonNull(queryIdList, "点位ID不可为空");
        if (homologyTypeEnum.equals(Constants.HomologyTypeEnum.ON_YEAR)) {

            ReportVo reportVo = dataChartService.compareChartReport(dataQueryDto);

            result.setHeaders(reportVo.getDateTimeList());
            List<HomologyChainBodyVO> bodyList = new ArrayList<>();
            result.setBodyList(bodyList);
            List<ReportDataVo> dataVoList = reportVo.getDataVoList();
            Map<String, ReportDataVo> curMap = dataVoList.stream().collect(Collectors.toMap(ReportDataVo::getClassifyName, v -> v, (e1, e2) -> e1));

            // 获取上年期值
            String lastYearStart = startDay.substring(0, 3) + (Integer.valueOf(startDay.substring(3, 4)) - 1) + startDay.substring(4);
            dataQueryDto.setStartDay(lastYearStart);
            ReportVo reportVoOld = dataChartService.compareChartReport(dataQueryDto);

            List<ReportDataVo> dataVoListOld = reportVoOld.getDataVoList();
            Map<String, ReportDataVo> oldMap = dataVoListOld.stream().collect(Collectors.toMap(ReportDataVo::getClassifyName, v -> v, (e1, e2) -> e1));

            curMap.forEach((k, v) -> {
                HomologyChainBodyVO vo = new HomologyChainBodyVO();
                vo.setName(k);
                Map<String, Object> dataMap = v.getDataMap();
                vo.setCurData(dataMap);
                ReportDataVo reportDataVo = oldMap.get(k);
                Map<String, Object> oldDataMap = reportDataVo.getDataMap();
                Map<String, Object> oldDataMap1 = new HashMap<>();
                vo.setOldData(oldDataMap1);
                Map<String, Object> ratioMap = new HashMap<>();
                dataMap.forEach((k1, v1) -> {
                    String k11 = k1.substring(0, 3) + (Integer.valueOf(k1.substring(3, 4)) - 1) + k1.substring(4);
                    if (oldDataMap.get(k11) == null || oldDataMap.get(k11).equals(BigDecimal.ZERO)) {
                        ratioMap.put(k1, "");
                        oldDataMap1.put(k1, 0);
                    } else {
                        BigDecimal v11 = (BigDecimal) v1;
                        BigDecimal old = (BigDecimal) oldDataMap.get(k11);
                        v11.subtract(old).divide(old, 2, RoundingMode.HALF_UP);
                        ratioMap.put(k1, v11.subtract(old).divide(old, 2, RoundingMode.HALF_UP));
                        oldDataMap1.put(k1, old);
                    }
                });
                vo.setRadio(ratioMap);
                bodyList.add(vo);
            });

        } else {

            ReportVo reportVo = dataChartService.compareChartReport(dataQueryDto);

            result.setHeaders(reportVo.getDateTimeList());
            List<HomologyChainBodyVO> bodyList = new ArrayList<>();
            result.setBodyList(bodyList);
            List<ReportDataVo> dataVoList = reportVo.getDataVoList();
            Map<String, ReportDataVo> curMap = dataVoList.stream().collect(Collectors.toMap(ReportDataVo::getClassifyName, v -> v, (e1, e2) -> e1));

            // 获取上年期值
            String lastLinkStartDate = DateUtils.addSubtractLinkRelative(queryType, startDay);
            dataQueryDto.setStartDay(lastLinkStartDate);
            ReportVo reportVoOld = dataChartService.compareChartReport(dataQueryDto);

            List<ReportDataVo> dataVoListOld = reportVoOld.getDataVoList();
            Map<String, ReportDataVo> oldMap = dataVoListOld.stream().collect(Collectors.toMap(ReportDataVo::getClassifyName, v -> v, (e1, e2) -> e1));

            curMap.forEach((k, v) -> {
                HomologyChainBodyVO vo = new HomologyChainBodyVO();
                vo.setName(k);
                Map<String, Object> dataMap = v.getDataMap();
                vo.setCurData(dataMap);
                ReportDataVo reportDataVo = oldMap.get(k);
                Map<String, Object> oldDataMap = reportDataVo.getDataMap();
                Map<String, Object> oldDataMap1 = new HashMap<>();

                vo.setOldData(oldDataMap1);
                Map<String, Object> ratioMap = new HashMap<>();
                dataMap.forEach((k1, v1) -> {
                    String k11 = DateUtils.addSubtractLinkRelative(queryType, k1, DateUtils.YMD_PATTERN);
                    if (oldDataMap.get(k11) == null || oldDataMap.get(k11).equals(BigDecimal.ZERO)) {
                        oldDataMap1.put(k1, 0);
                        ratioMap.put(k1, "");
                    } else {
                        BigDecimal v11 = (BigDecimal) v1;
                        BigDecimal old = (BigDecimal) oldDataMap.get(k11);
                        if (old.compareTo(BigDecimal.ZERO) != 0) {
                            BigDecimal divide = v11.subtract(old).divide(old, 2, RoundingMode.HALF_UP);
                            ratioMap.put(k1, divide);
                        } else {
                            ratioMap.put(k1, "");
                        }
                        oldDataMap1.put(k1, old);
                    }
                });
                vo.setRadio(ratioMap);
                bodyList.add(vo);
            });

        }

        return result;
    }

    @Override
    public void export(HttpServletResponse response, DataQueryDto dataQueryDto, Integer homologyType) {
        HomologyChainVO homologyChainVO = list(dataQueryDto, homologyType);

        HomologyChainExportUtil homologyChainExportUtil = new HomologyChainExportUtil();
        if (homologyType.equals(1)) {
            // 环比
            homologyChainExportUtil.complexFillWithTable2(response, homologyChainVO, dataQueryDto.getQueryType());
        } else {
            homologyChainExportUtil.complexFillWithTable1(response, homologyChainVO);

        }

    }

    /**
     * 周环比
     * @param dataQueryDto
     * @return
     */
    @Override
    public HomologyChainVO dataChain(DataQueryDto dataQueryDto) {
        // 根据数据字典配置找到对应分类id
        String classifyId = getclassifyId(dataQueryDto.getDictCode(), dataQueryDto.getItemName());
        dataQueryDto.setClassifyId(classifyId);
        HomologyChainVO result = new HomologyChainVO();

        //根据查询条件计算起止时间
        dataQueryDto.setQueryType(DateType.WEEK);
        String queryType = DateType.WEEK;
        DateDto dateDto = DateUtils.dateQueryConvert(queryType, dataQueryDto.getStartDay(), dataQueryDto.getEndDay(), true);
        // 构建x轴
        List<LocalDateTime> list = DateUtils.dateToList(queryType, dateDto.getStartDay(), dateDto.getEndDay());
        List<String> headers = new ArrayList<>();
        for (int i = 1; i <= list.size(); i++) {
            headers.add(String.valueOf(i));
        }
        result.setHeaders(headers);

        AssertUtil.nonNull(dataQueryDto.getClassifyId(), "点位ID不可为空");

        // 构建Y轴
        // 本周数据
        dataQueryDto.setClassifyIdList(Collections.singletonList(dataQueryDto.getClassifyId()));
        ReportVo reportVoCur = dataChartService.compareChartReport(dataQueryDto);

//        result.setHeaders(reportVoCur.getDateTimeList());
        List<HomologyChainBodyVO> bodyList = new ArrayList<>();
        result.setBodyList(bodyList);
        List<ReportDataVo> dataVoList = reportVoCur.getDataVoList();
        Map<String, ReportDataVo> curMap = dataVoList.stream().collect(Collectors.toMap(ReportDataVo::getClassifyName, v -> v, (e1, e2) -> e1));

        // 获取上周
        dataQueryDto.setStartDay(dataQueryDto.getLastStartDay());
        ReportVo reportVoOld = dataChartService.compareChartReport(dataQueryDto);

        List<ReportDataVo> dataVoListOld = reportVoOld.getDataVoList();
        Map<String, ReportDataVo> oldMap = dataVoListOld.stream().collect(Collectors.toMap(ReportDataVo::getClassifyName, v -> v, (e1, e2) -> e1));
        curMap.forEach((k, v) -> {
            HomologyChainBodyVO vo = new HomologyChainBodyVO();
            vo.setName(k);
            Map<String, Object> dataMap = v.getDataMap();
            vo.setCurData(dataMap);
            ReportDataVo reportDataVo = oldMap.get(k);
            Map<String, Object> oldDataMap = reportDataVo.getDataMap();
            Map<String, Object> oldDataMap1 = new HashMap<>();

            vo.setOldData(oldDataMap1);
            Map<String, Object> ratioMap = new HashMap<>();
            dataMap.forEach((k1, v1) -> {
                // 找到上周对比的日期查询数据计算环比数据
                String k11 = DateUtils.getLastWeekday(k1);
                if (oldDataMap.get(k11) == null || oldDataMap.get(k11).equals(BigDecimal.ZERO)) {
                    oldDataMap1.put(k11, 0);
                    ratioMap.put(k1, "");
                } else {
                    BigDecimal v11 = (BigDecimal) v1;
                    BigDecimal old = (BigDecimal) oldDataMap.get(k11);
                    if (old.compareTo(BigDecimal.ZERO) != 0) {
                        BigDecimal divide = v11.subtract(old).divide(old, 4, RoundingMode.HALF_UP);
                        ratioMap.put(k1, divide.multiply(new BigDecimal("100")).setScale(2, RoundingMode.HALF_UP)+"%");
                    } else {
                        ratioMap.put(k1, "");
                    }
                    oldDataMap1.put(k11, old);
                }
            });
            vo.setRadio(ratioMap);
            bodyList.add(vo);
        });

        // 针对日期进行排序
        result.getBodyList().get(0).setCurData(
                mapSort(result.getBodyList().get(0).getCurData())
        );
        result.getBodyList().get(0).setOldData(
                mapSort(result.getBodyList().get(0).getOldData())
        );
        result.getBodyList().get(0).setRadio(
                mapSort(result.getBodyList().get(0).getRadio())
        );

        return result;
    }

    @Override
    public HomologyChainVO  totalDataChain(DataQueryDto dataQueryDto) {
        HomologyChainVO result = new HomologyChainVO();
        HomologyChainVO detailData = dataChain(dataQueryDto);
        result.setHeaders(Arrays.asList("上周电量", "本周电量"));
        HomologyChainBodyVO weekData = detailData.getBodyList().get(0);
        if(weekData.getCurData().isEmpty() || weekData.getOldData().isEmpty()){
            throw new RuntimeException("缺少本周或上周电量");
        }
        // 上周
        BigDecimal oldSum = weekData.getOldData().values().stream()
                .map(value -> value instanceof Integer ? new BigDecimal((Integer) value) : (BigDecimal) value)// 将 Object 类型转换为 BigDecimal 类型
                .reduce(BigDecimal.ZERO, BigDecimal::add); // 对 BigDecimal 类型的值进行求和;
        // 本周
        BigDecimal curSum = weekData.getCurData().values().stream()
                .map(value -> value instanceof Integer ? new BigDecimal((Integer) value) : (BigDecimal) value)// 将 Object 类型转换为 BigDecimal 类型
                .reduce(BigDecimal.ZERO, BigDecimal::add); // 对 BigDecimal 类型的值进行求和;

        // 环比值
        Map<String,Object> radioMap = new HashMap<>();
        if(oldSum.compareTo(BigDecimal.ZERO)==0) {
            radioMap.put("环比增长率","-");
        }else{
            radioMap.put(
                    "环比增长率",
                    curSum.subtract(oldSum)
                            .divide(oldSum,4,RoundingMode.HALF_UP)
                            .multiply(new BigDecimal("100"))
                            .setScale(2, RoundingMode.HALF_UP)+"%"
            );
        }

        HomologyChainBodyVO bodyData = new HomologyChainBodyVO();
        bodyData.setOldData(new HashMap<>() {{
            put("上周电量", oldSum);
        }});
        bodyData.setCurData(new HashMap<>() {{
            put("本周电量", curSum);
        }});
        bodyData.setRadio(radioMap);
        result.setBodyList(List.of(bodyData));
        return result;
    }

    // 根据日期进行排序
    public Map<String,Object> mapSort(Map<String,Object> map){
        Map<String, Object> sortMap = new TreeMap<>((dateStr1, dateStr2) -> {
            LocalDate date1 = LocalDate.parse(dateStr1);
            LocalDate date2 = LocalDate.parse(dateStr2);
            return date1.compareTo(date2);
        });
        sortMap.putAll(map);
        return sortMap;
    }

    @Nullable
    private String getclassifyId(String dictCode, String itemName) {
        String classifyId = null;
        // 获取字典配置分类项
        List<DictItem> dictItems = dictItemService.getByDictCode(dictCode);
        if (dictItems.isEmpty()) {
            classifyId = null;
        } else {
            DictItem dictItem = dictItems.stream().filter(m -> m.getItemName().equals(itemName)).findFirst().orElse(new DictItem());
            classifyId = dictItem.getItemCode();
        }
        AssertUtil.nonNull(classifyId, "未找到字典配置");
        return classifyId;
    }



}
